﻿using EasyCore.DependencyInjection.Attributes;
using EasyCore.DependencyInjection.Interfaces;
using EasyCore.Entities;
using EasyCore.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EasyCore.DependencyInjection
{
    /// <summary>
    /// 依赖注入
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加类型，到依赖注入内
        /// </summary>
        public static void AddInjectionTypes(this IServiceCollection services)
        {
            

            var canInjectTypes = AssemblyManager.FindTypes(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.HasAttribute<IgnoreDependencyAttribute>(false)
            && (typeof(IPrivateDependency).IsAssignableFrom(x)) || x.HasAttribute<DependencyAttribute>(false));//获得系统内部所有能依赖注入的类型
            if (canInjectTypes == null || !canInjectTypes.Any()) return;//没有能够依赖注入的类型时，则返回                                                                                      
            foreach (var type in canInjectTypes)
            {
                var lifttime = GetServiceLifetime(type);  //获得类型的生命周期
                if (lifttime == null) continue;
                var canInjectInterfaces = GetInjectInterfacesByType(type); //获得类型的所有接口
                if (canInjectInterfaces == null || canInjectInterfaces.Count == 0)
                {
                    services.TryAdd(new ServiceDescriptor(type, type, lifttime.Value)); //依赖注入其自已
                    continue;
                }
                foreach (var serviceType in canInjectInterfaces)
                {
                    if (serviceType.HasAttribute<ExcludeDependencyAttribute>() || serviceType.HasAttribute<ExcludeDependencyAttribute>()) continue;  //排除某种接口依赖注入             
                    services.TryAdd(new ServiceDescriptor(serviceType, type, lifttime.Value)); //依赖注入其接口
                }
            }
        }

        /// <summary>
        /// 获得服务的生命周期
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static ServiceLifetime? GetServiceLifetime(Type type)
        {
            if (type.IsDeriveClassFrom(typeof(ISingletonDependency))) return ServiceLifetime.Singleton;
            if (type.IsDeriveClassFrom(typeof(ITransientDependency))) return ServiceLifetime.Transient;
            if (type.IsDeriveClassFrom(typeof(IScopedDependency))) return ServiceLifetime.Scoped;
            DependencyAttribute attribute = type.GetAttribute<DependencyAttribute>();
            if (attribute != null) return attribute.Lifetime;
            return null;//缺省的生命周期
        }

        /// <summary>
        /// 获得类型的所有父型（能够依赖注入的类型）
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<Type> GetInjectInterfacesByType(Type type)
        {
            var interfaces = type.GetInterfaces(); //获得类型的所有接口
            var canInjectInterfaces = interfaces.Where(x => x != typeof(IPrivateDependency) && x != typeof(ISingletonDependency)
            && x != typeof(IScopedDependency) && x != typeof(ITransientDependency) && x != typeof(IDisposable) && x != typeof(IAsyncDisposable)
            && !x.HasAttribute<IgnoreDependencyAttribute>() && !x.HasAttribute<ExcludeDependencyAttribute>()).ToList(); // && ((!x.IsGenericType && !type.IsGenericType) || (x.IsGenericType && type.IsGenericType && x.GetGenericArguments().Length == type.GetGenericArguments().Length))
            List<Type> resultInterfaces = new List<Type>();
            for (int index = 0; index < canInjectInterfaces.Count; index++)
            {
                Type tempInterface = canInjectInterfaces[index];
                if (!tempInterface.IsGenericType)
                {
                    resultInterfaces.Add(tempInterface);
                    continue;
                }
                if (!tempInterface.IsGenericTypeDefinition && !string.IsNullOrWhiteSpace(tempInterface.FullName))
                {
                    resultInterfaces.Add(tempInterface.GetGenericTypeDefinition()); //获得泛型定义
                }
            }
            return resultInterfaces;
        }
    }
}
